# v0.21.0

## 支持 Wasm 扩展框架

### Config
```text
{
  "servers": [
    {
      "default_log_path": "stdout",
      "routers": [
        {
          "router_config_name": "server_router",
          "virtual_hosts": [
            {
              "name": "serverHost",
              "domains": ["*"],
              "routers": [
                {
                  "direct_response": {
                    "status": 200
                  }
                }
              ]
            }
          ]
        }
      ],
      "listeners": [
        {
          "address": "0.0.0.0:2045",
          "bind_port": true,
          "filter_chains": [
            {
              "filters": [
                {
                  "type": "proxy",
                  "config": {
                    "downstream_protocol": "Http1",
                    "upstream_protocol": "Http1",
                    "router_config_name": "server_router"
                  }
                }
              ]
            }
          ],
          "stream_filters": [
            {
              "type": "proxywasm",
              "config": {
                "instance_num": 1,
                "vm_config": {
                  "engine": "wasmer",
                  "path": "/etc/wasm/filter.wasm"
                }
              }
            }
          ]
        }
      ]
    }
  ]
}
```

### Run

```text
1. Start MOSN
> docker run -it -rm -p 2045:2045 -v $(pwd):/etc/wasm/ mosnio/mosn-wasm:v0.21.0

2. Curl
> curl -v http://127.0.0.1:2045/
```

#### Result
```text
1. MOSN log:
[INFO] proxywasm get request headers...
[INFO] request header from go wasm --> Host: 127.0.0.1:2045
[INFO] request header from go wasm --> Content-Length: 0
[INFO] request header from go wasm --> User-Agent: curl/7.64.1
[INFO] request header from go wasm --> Accept: */*
[INFO] proxywasm add singe header...

2. Curl:
< HTTP/1.1 200 OK
< Date: Fri, 02 Apr 2021 07:06:26 GMT
< Content-Length: 0
< Host: 127.0.0.1:2045
< User-Agent: curl/7.64.1
< Accept: */*
< Go-Wasm-Header: hello wasm
< 
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0
```

## 支持基于 Wasm 的协议编解码能力 (x-bolt 子协议)

### Config
```json
{
  "servers": [
    {
      "routers": [
        {
          "router_config_name": "client_router",
          "virtual_hosts": [
            {
              "name": "clientHost",
              "domains": [
                "*"
              ],
              "routers": [
                {
                  "match": {
                    "headers": [
                      {
                        "name": "service",
                        "value": ".*"
                      }
                    ]
                  },
                  "route": {
                    "cluster_name": "clientCluster"
                  }
                }
              ]
            }
          ]
        }
      ],
      "listeners": [
        {
          "name": "clientListener",
          "address": "127.0.0.1:2045",
          "bind_port": true,
          "filter_chains": [
            {
              "filters": [
                {
                  "type": "proxy",
                  "config": {
                    "downstream_protocol": "X",
                    "upstream_protocol": "X",
                    "router_config_name": "client_router",
                    "extend_config": {
                      "sub_protocol": "x-bolt"
                    }
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ],
  "cluster_manager": {
    "clusters": [
      {
        "name": "clientCluster",
        "type": "SIMPLE",
        "lb_type": "LB_RANDOM",
        "hosts": [
          {
            "address": "127.0.0.1:2046"
          }
        ]
      }
    ]
  },
  "wasm_global_plugins": [
    {
      "plugin_name": "wasm-bolt",
      "vm_config": {
        "engine": "wasmer",
        "path": "etc/wasm/bolt-go.wasm"
      }
    }
  ],
  "third_part_codec": {
    "codecs": [
      {
        "type": "wasm",
        "enable": true,
        "config": {
          "from_wasm_plugin": "wasm-bolt",
          "protocol": "x-bolt",
          "root_id": 1
        }
      }
    ]
  }
}
```

### Run
```text
1. Get Sofa Server and Client
> git clone https://github.com/sofastack-guides/sofastack-mesh-demo.git
> cd sofastack-mesh-demo
> git checkout wasm_benchmark
> cd sofa-samples-springboot2

2. Build Server and Client
mvn clean package

3. Start Sofa Server
> java -DMOSN_ENABLE=true -Drpc_tr_port=12199 -Dspring.profiles.active=dev -Drpc_register_registry_ignore=true -jar ./sofa-echo-server/target/sofa-echo-server-web-1.0-SNAPSHOT-executable.jar

4. Start Sofa Client
> java  -DMOSN_ENABLE=true -Drpc_tr_port=12198 -Dspring.profiles.active=dev -Drpc_register_registry_ignore=true -jar ./sofa-echo-client/target/sofa-echo-client-web-1.0-SNAPSHOT-executable.jar
```

### Result
```text
>>>>>>>> [41,5,9ms]2021-04-02 15:37:43 echo result: Hello world!
>>>>>>>> [41,6,11ms]2021-04-02 15:37:44 echo result: Hello world!
>>>>>>>> [41,7,8ms]2021-04-02 15:37:45 echo result: Hello world!
>>>>>>>> [41,8,8ms]2021-04-02 15:37:46 echo result: Hello world!
>>>>>>>> [41,9,7ms]2021-04-02 15:37:47 echo result: Hello world!
>>>>>>>> [41,10,8ms]2021-04-02 15:37:48 echo result: Hello world!
>>>>>>>> [41,11,9ms]2021-04-02 15:37:49 echo result: Hello world!
>>>>>>>> [41,12,9ms]2021-04-02 15:37:50 echo result: Hello world!
>>>>>>>> [41,13,8ms]2021-04-02 15:37:51 echo result: Hello world!
>>>>>>>> [41,14,18ms]2021-04-02 15:37:52 echo result: Hello world!
```


## 支持自动协议识别失败时的兜底能力

### Config
```json
{
  "servers": [
    {
      "default_log_path": "stdout",
      "routers": [
        {
          "router_config_name": "router_to_http_server",
          "virtual_hosts": [
            {
              "name": "server_hosts",
              "domains": [
                "*"
              ],
              "routers": [
                {
                  "match": {
                    "prefix": "/"
                  },
                  "route": {
                    "cluster_name": "server_http_cluster"
                  }
                }
              ]
            }
          ]
        }
      ],
      "listeners": [
        {
          "address": "127.0.0.1:2046",
          "bind_port": true,
          "filter_chains": [
            {
              "filters": [
                {
                  "type": "proxy",
                  "config": {
                    "fallback_for_unknown_protocol": true,
                    "downstream_protocol": "Auto",
                    "upstream_protocol": "Http1",
                    "router_config_name": "router_to_http_server"
                  }
                },
                {
                  "type": "tcp_proxy",
                  "config": {
                    "cluster": "server_tcp_cluster"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ],
  "cluster_manager": {
    "clusters": [
      {
        "name": "server_http_cluster",
        "type": "SIMPLE",
        "lb_type": "LB_RANDOM",
        "hosts": [
          {
            "address": "127.0.0.1:8080"
          }
        ]
      },
      {
        "name": "server_tcp_cluster",
        "type": "SIMPLE",
        "lb_type": "LB_RANDOM",
        "hosts": [
          {
            "address": "127.0.0.1:9090"
          }
        ]
      }
    ]
  }
}
```

### TCP Server
```go
package main

import (
	"fmt"
	"net"
)

func main() {
	l, err := net.Listen("tcp", "127.0.0.1:9090")
	if err != nil {
		fmt.Println("fail to start tcp server")
		return
	}
	defer l.Close()

	for {
		conn, err := l.Accept()
		if err != nil {
			fmt.Println("fail to accept tcp connection")
		}

		go handleRequest(conn)
	}
}

func handleRequest(conn net.Conn) {
	fmt.Println("Accepted new connection.")
	defer conn.Close()

	for {
		buf := make([]byte, 1024)
		size, err := conn.Read(buf)
		if err != nil {
			return
		}
		data := buf[:size]
		fmt.Println("Read new data from connection:", string(data))
		conn.Write(data)
	}
}
```

### Run
```text
2. TCP Request
> echo "helloworlddddddddddddddddddddd" | netcat 127.0.0.1 2046
```

### Result
```text
Accepted new connection.
Read new data from connection: helloworlddddddddddddddddddddd
```